\insert 'NewPortObject.oz'
% Messages sent to the Dating Service
% seeking(MySex MeDescription OtherSex OtherDescription ResponsePort)
% Messages sent by the Dating service on ResponsePort
% list(CompatiblePeople)
% match(CompatiblePerson)

%% The port object factory
declare
fun {GetMatches PotenialMatches Msg}
   case Msg of seeking(MySex MyDesc OtherSex OtherDesc _) then
      {Filter PotenialMatches
       fun {$ seeking(_ HasDesc WishedSex WishedDesc _)}
	  MySex==WishedSex andthen MyDesc==WishedDesc andthen OtherDesc==HasDesc
       end}
   end
end

proc {SendMessages Compatible ResponsePort MySex MyDesc OtherSex OtherDesc}
   case Compatible of nil then skip
   else
      {Send ResponsePort list(Compatible)}
      for seeking(_ _ _ _ RP) in Compatible do
	 {Send RP match(MySex MyDesc OtherSex OtherDesc ResponsePort)}
      end
   end
end

fun {NewDatingService}
   {NewPortObject state(women: nil men: nil)
    fun {$ state(women: Women men: Men) Msg}
       case Msg of seeking(female MyDesc OtherSex OtherDesc ResponsePort) then
	  local Matches in
	     Matches = {GetMatches Men Msg}
	     {SendMessages Matches ResponsePort female MyDesc OtherSex OtherDesc}
	     state(women: Msg|Women men: Men)
	  end
       [] seeking(male MyDesc OtherSex OtherDesc ResponsePort) then
	  local Matches in
	     Matches = {GetMatches Women Msg}
	     {SendMessages Matches ResponsePort male MyDesc OtherSex OtherDesc}
	     state(women: Women men: Msg|Men)
	  end
       end
    end
   }
end

DatingService = {NewDatingService}
fun {NewClient Name MySex MyDesc OtherSex OtherDesc}
   RP = {NewPortObject2
	 proc {$ Msg}
	    {Browse Name#' got '#Msg}
	 end}
in
   {Send DatingService seeking(MySex MyDesc OtherSex OtherDesc RP)}
   RP
end

Alice = {NewClient 'Alice' female blond male dark}
Bob = {NewClient 'Bob' male dark female blond}
Candice = {NewClient 'Candice' female blond male dark}
Dale = {NewClient 'Dale' male dark female blond}
Elise = {NewClient 'Elise' female brunette male blond}
Fred = {NewClient 'Fred' male blond female brunette}
{Browse done}